package com.tang.server;

import com.tang.domain.*;
import com.tang.util.CacheUtil;
import com.tang.util.FileUtil;
import com.tang.util.MsgUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.time.LocalDateTime;

/**
 * 自定义消息处理类
 *
 * @author fulin.tang
 * @version V3.0
 * @since 2022/3/11 17:34
 */
@Slf4j
public class MyServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        log.info("有新的连接：CHANNEL_ID:{}, ADDRESS:{}", ctx.channel().id(), ctx.channel().localAddress());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        log.info("客户端断开链接{}", ctx.channel().localAddress());
    }

    /**
     * netty接收数据
     *
     * @param ctx netty通道handler
     * @param msg 收到的消息
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws IOException {

        // 数据格式验证
        if (!(msg instanceof FileTransferProtocol)) {
            log.info("数据格式不对");
            return;
        }

        FileTransferProtocol fileTransferProtocol = (FileTransferProtocol) msg;

        switch (fileTransferProtocol.getTransferType()) {
            case 0: // 请求传输文件
                FileInfo fileDescInfo = (FileInfo) fileTransferProtocol.getTransferObj();
                FileSliceInstruct fileBurstInstructOld = CacheUtil.burstDataMap.get(fileDescInfo.getFileName());
                if (null != fileBurstInstructOld) {
                    if (fileBurstInstructOld.getStatus() == Constants.FileStatus.COMPLETE) {
                        CacheUtil.burstDataMap.remove(fileDescInfo.getFileName());
                    }
                    // 传输完成删除断点信息
                    log.info("{} 服务端，接收客户端传输文件请求【断点续传】。{}", LocalDateTime.now(), fileBurstInstructOld);
                }

                // 发送消息
                FileTransferProtocol sendFileTransferProtocol = MsgUtil.buildTransferInstruct(Constants.FileStatus.BEGIN, fileDescInfo.getFileUrl(), 0);
                ctx.writeAndFlush(sendFileTransferProtocol);
                log.info("{} 服务端，接收客户端传输文件请求。{}", LocalDateTime.now(), fileDescInfo);
                break;
            case 2: // 文件传输数据
                FileSliceData fileBurstData = (FileSliceData) fileTransferProtocol.getTransferObj();
                FileSliceInstruct fileBurstInstruct = FileUtil.writeFile("D://", fileBurstData);

                // 保存断点续传信息
                CacheUtil.burstDataMap.put(fileBurstData.getFileName(), fileBurstInstruct);

                ctx.writeAndFlush(MsgUtil.buildTransferInstruct(fileBurstInstruct));
                log.info("{}, 服务端，接收客户端传输文件数据。{}", LocalDateTime.now(), fileBurstData);

                // 传输完成删除断点信息
                if (fileBurstInstruct.getStatus() == Constants.FileStatus.COMPLETE) {
                    CacheUtil.burstDataMap.remove(fileBurstData.getFileName());
                }

                break;
            default:
                break;
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        log.info("异常信息：\r\n{}", cause.getMessage());
    }

}
